/**
 * Generator实现的核心在于上下文的保存，函数并没有真的被挂起.
 * 每一次yield，其实都执行了一遍传入的生成器函数，只是在这个过程中间用了一个context对象储存上下文，
 * 使得每次执行生成器函数的时候，都可以从上一个执行结果开始执行，看起来就像函数被挂起了一样
 * 
 * 1.新建一个上下文（Context）的类
 * 2.新建一个gen$（context）函数，判断返回什么值，用的switch
 *    取值的时候给next赋新值，判断的时候把next值给prev
 *      context.prev = context.next
 *      context.next = xxx
 *    在需要的时候给变量赋值，a = context.sent
 *    
 * 3.Generator函数转化后的函数
 *    返回next函数，调用next会返回value和done
 * 
 */

function* foo1() {
  var a = yield 'result1'
  console.log(a);
  yield 'result2'
  yield 'result3'
}

// 用一个全局变量
class Context {
  constructor(sent) {
    this.prev = 0
    this.next = 0
    this.done = false
    this.sent = sent
  }
  setSent(sent) {
    this.sent = sent
  }
  // 改变自身的状态
  stop() {
    this.done = true
  }
}

function gen$(context) {
  let a
  while (1) {
    switch (context.prev = context.next) {
      case 0:
        context.next = 2
        return 'result1';
      case 2:
        a = context.sent
        context.next = 4
        console.log('a:' + a);
        return 'result2';
      case 4:
        context.next = 6
        return 'result3'
      case 6:
        // 更改状态
        context.stop()
        return 'undefined';
    }
  }
}
// Generator函数转化后的函数
let foo = function () {
  let context = new Context()
  return {
    next(param) {
      context.setSent(param)
      value = gen$(context)
      done = context.done
      return {
        value, done
      }
    }
  }
}

let gen = foo()
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());
console.log(gen.next());






// 采用闭包+switch,实际底层不是这个
// function gen$() {
//   let nextStep = 0
//   return function () {
//     while (1) {
//       switch (nextStep) {
//         case 0:
//           nextStep = 2
//           return 'result1';
//         case 2:
//           nextStep = 4
//           return 'result2';
//         case 4:
//           nextStep = 6
//           return 'result3';
//         case 6:
//           return undefined;
//       }
//     }
//   }
// }
// let a = gen$()













